package com.bs.message.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;

/**
 * @author J
 */
@Configuration
public class RabbitConfig {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    ConnectionFactory connectionFactory;
    public RabbitConfig(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    @Bean
    public Queue coreQueue() {
        return new Queue("api.core");
    }

    @Bean
    public TopicExchange coreExchange() {
        return new TopicExchange("topic.core");
    }
    @Bean
    public Binding coreBind() {
        return BindingBuilder.bind(coreQueue()).to(coreExchange()).with("api.#");
    }

    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    //@Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        // 消息路由失败通知监听者
        rabbitTemplate.setMandatory(true);
        // 发送成功确认：消息唯一标识，确认结果，失败原因
        rabbitTemplate.setConfirmCallback((correlationData, b, s) -> {
            if (b){
                logger.info("消息发送至交换机成功:correlationData({}),ack({}),cause({})",correlationData,b,s);
            } else {
                logger.info("消息发送至交换机失败:correlationData({}),ack({}),cause({})",correlationData,b,s);
            }
        });
        // 路由不到队列触发回调，
        rabbitTemplate.setReturnCallback((message, i, s, s1, s2) -> {
            logger.info("交换机无法将信息发送至队列:exchange({}),route({}),replyCode({}),replyText({}),message:{}",s1,s2,i,s,message);
        });
        // 消息转json
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
        // 重试机制
        rabbitTemplate.setRetryTemplate(retryTemplate());

        return rabbitTemplate;
    }

    /**
     * 重试机制针对的是网络不稳定导致的连接中断的问题，而不是消息的重发
     * @return RetryTemplate
     */
    @Bean
    public RetryTemplate retryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();
        SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy(Integer.MAX_VALUE);
        retryTemplate.setRetryPolicy(simpleRetryPolicy);
        return retryTemplate;
    }

}
